<?php

namespace App\Service\WorkOrder\ProductSelectionProposal;

use App\Enums\BaseErrorCode;
use App\Enums\WorkOrder\ErrCode;
use App\Enums\WorkOrder\MissionEnum;
use App\Exceptions\Custom\CustomHttpResponseException;
use App\Exceptions\Custom\ResponseHttpException;
use App\Library\Rms\RmsShopApi;
use App\Models\Common\ConfigModel;
use App\Models\Common\ResourcesModel;
use App\Models\Shop\ShopModel;
use App\Models\WorkOrder\ProductSelectionProposal\WorkOrderProductSelectionProposalModel;
use App\Models\WorkOrder\WorkOrderApplyContentModel;
use App\Models\WorkOrder\WorkOrderOperateLogModel;
use App\Service\BaseService;
use App\Support\CustomForm\AttributeWorkOrderSupport;
use App\Support\CustomForm\ValidateSupport;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class ProductSelectionProposalService extends BaseService
{


    const AUTOINCREMENT_REDIS_KEY = 'WORK_ORDER_NO:PRODUCT_SELECTION_PROPOSAL:';

    /**
     * 获取表单
     * @param int $userId
     * @param string $userMobile
     * @param string $userName
     * @param array $parameter
     * @return array
     */
    public static function getProductSelectionProposalForm(int $userId, string $userMobile, string $userName, array $parameter = []): array
    {
        self::getBaseForm();

        if (!$parameter && $userMobile && $userName) {
            $parameter['name']   = $userName;
            $parameter['mobile'] = $userMobile;
        }

        $res = collect(AttributeWorkOrderSupport::$attributesMap)
            ->map(
                function (AttributeWorkOrderSupport $attribute) use ($parameter) {
                    return $attribute->setValue(
                        function () use ($parameter, $attribute) {
                            if ($parameter) {
                                return $parameter[$attribute->getInputName()] ?? null;
                            }
                        }
                    )->build();
                }
            )->values()->toArray();

        return [
            'title' => '选品建议',
            'desc'  => '',
            'form'  => $res,
        ];
    }

    /**
     * 获取提交次数
     * @param int $userId
     * @param int $type
     * @return array
     */
    public static function getSubmitNum(int $userId, int $type = WorkOrderProductSelectionProposalModel::TYPE_FRANCHISEE): array
    {
        // 统计周期为单个自然月
        $startTime = date('Y-m-01', strtotime("now")); // 获取当前月的第一天
        $endTime   = date('Y-m-t 23:59:59', strtotime("now"));  // 获取当前月的最后一天

        $num = WorkOrderProductSelectionProposalModel::query()
            ->whereBetween('createdAt', [strtotime($startTime), strtotime($endTime)])
            ->where('createdByUid', $userId)
            ->count();

        $limit = Cache::remember(
            'workOrder:productSelectionProposal', getSwitchCacheTime(300), function () {
            return ConfigModel::query()
                ->where('module', 'workOrder')
                ->where('name', 'productSelectionProposal')
                ->value('value');
        }
        );

        return [
            'num'      => $num,          // 已提交次数
            'limit'    => $limit,        // 周期内限制次数
            'isSubmit' => $num < $limit, // 当前周期内是否可提交
        ];
    }


    /**
     * 提交表单
     * @param array $params
     * @param int $shopId
     * @param int $userId
     * @param string $userName
     * @param int $type
     * @return string[]
     */
    public static function submitForm(
        array $params,
        int $shopId,
        int $userId,
        string $userName,
        int $type = WorkOrderProductSelectionProposalModel::TYPE_FRANCHISEE
    ): array
    {

        // 检查是否可提交
        $getSubmitData = self::getSubmitNum($userId, $type);
        if (!$getSubmitData['isSubmit']) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "每个选品周期至多提交" . $getSubmitData['limit'] . "条建议，您可在下个选品周期再次提交");
        }

        //获取资源文件
        $fileArr = [
            'productImgVideo',
        ];

        $resources = [];
        foreach ($fileArr as $value) {
            if (isset($params[$value])) {
                $resources[$value] = $params[$value];
                unset($params[$value]);
            }
        }

        $prefix      = 'XP';
        $next        = '01';
        $dateTime    = date('YmdHis');
        $count       = str_pad(self::autoincrementByRedis($prefix . $next), 4, '0', STR_PAD_LEFT);
        $workOrderNo = $prefix . $next . $dateTime . $count;

        try {
            DB::beginTransaction();

            // 主表
            WorkOrderProductSelectionProposalModel::query()->create(
                [
                    'workOrderNo' => $workOrderNo,
                    'shopId'      => $shopId,
                    'type'        => $type,
                ]
            );

            // 详情
            $contentInfo = WorkOrderApplyContentModel::query()->create(
                [
                    'workOrderNo' => $workOrderNo,
                    'content'     => json_encode($params, JSON_UNESCAPED_UNICODE),
                ]
            );

            //日志 - 提交工单
            WorkOrderOperateLogModel::generateOperateLog(
                $workOrderNo,
                MissionEnum::STEP_1,
                WorkOrderOperateLogModel::TYPE_1,
                $userName,
                $userId,
                '提交工单'
            );


            // 文件添加
            if ($resources) {
                $insertData = [];
                foreach ($resources as $key => $resource) {
                    if (is_array($resource)) {
                        foreach ($resource as $item) {
                            $insertData[] = [
                                'businessId'   => $contentInfo->id,
                                'module'       => ResourcesModel::MODULE_TYPE_WORK_ORDER_PRODUCT_SELECTION_PROPOSAL,
                                'business'     => ResourcesModel::BUSINESS_TYPE_WORK_ORDER_PRODUCT_SELECTION_PROPOSAL,
                                'name'         => $key,
                                'url'          => $item['path'],
                                'isPublic'     => ResourcesModel::IS_PUBLIC_YES,
                                'createdAt'    => time(),
                                'updatedAt'    => time(),
                                'createdByUid' => $userId,
                                'updatedByUid' => $userId,
                                'extra'        => json_encode($item, JSON_UNESCAPED_UNICODE),
                            ];
                        }
                    }
                }
                ResourcesModel::query()->insert($insertData);
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::info(
                'WorkOrderProductSelectionProposalAddErr', [
                    'params'      => $params,
                    'shopId'      => $shopId,
                    'userId'      => $userId,
                    'userName'    => $userName,
                    'type'        => $type,
                    'workOrderNo' => $workOrderNo,
                    'msg'         => $e->getMessage(),
                ]
            );
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, '提交失败');
        }

        return ['workOrderNo' => $workOrderNo];
    }

    /**
     * 获取历史提交记录
     * @param int $userId
     * @param int $pageNum
     * @param int $pageSize
     * @param int $type
     * @return array
     */
    public static function lists(
        int $userId,
        int $pageNum,
        int $pageSize,
        int $type = WorkOrderProductSelectionProposalModel::TYPE_FRANCHISEE
    ): array
    {
        $paginates = WorkOrderProductSelectionProposalModel::query()
            ->with(['contentRel'])
            ->where('createdByUid', $userId)
            ->orderByDesc('createdAt')
            ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        return [
            'lists'    => $paginates->map(
                function ($item) {
                    $content    = json_decode($item->contentRel->content ?? '', true) ?? [];
                    $status     = $item->status;
                    $statusText = WorkOrderProductSelectionProposalModel::ADOPT_STATUS_TEXT[$item->status] ?? '';
                    if (in_array($item->status, [WorkOrderProductSelectionProposalModel::ADOPT_STATUS_ONLINE, WorkOrderProductSelectionProposalModel::ADOPT_STATUS_HOT])) {
                        $status = WorkOrderProductSelectionProposalModel::ADOPT_STATUS_ACCEPTED;// 已采纳
                    }
                    return [
                        'workOrderNo'  => $item->workOrderNo,
                        'productTitle' => $content['productTitle'] ?? '',
                        'createdAt'    => date('Y-m-d H:i:s', $item->createdAt->timestamp),
                        'status'       => $status,
                        'statusText'   => $statusText,
                    ];
                }
            ),
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize,
            'count'    => $paginates->total(),
        ];
    }

    /**
     * 通过工单号获取详情
     * @param string $workOrderNo
     * @param int $userId
     * @param bool $isWeb
     * @return array
     */
    public static function detail(string $workOrderNo, int $userId = 0, bool $isWeb = false): array
    {

        // 通过工单号获取详情
        $info = WorkOrderProductSelectionProposalModel::query()
            ->where('workOrderNo', $workOrderNo)
            ->when(
                $userId, function ($query) use ($userId) {
                $query->where('createdByUid', $userId);
            }
            )
            ->first();

        $contentInfo = WorkOrderApplyContentModel::query()
            ->where('workOrderNo', $workOrderNo)
            ->select('id', 'content')
            ->first();

        if (null === $info || null === $contentInfo) {
            throw new CustomHttpResponseException(ErrCode::errCodeTrans(ErrCode::CODE_ERR_WORK_ORDER_NO));
        }

        // 基本数据
        $argument = json_decode($contentInfo['content'], true);

        // 文件资源字段
        $fileKey = [
            'productImgVideo',
        ];

        // 文件数据
        $resources = ResourcesModel::getModuleBusinessBatchResources(
            ResourcesModel::MODULE_TYPE_WORK_ORDER_PRODUCT_SELECTION_PROPOSAL,
            ResourcesModel::BUSINESS_TYPE_WORK_ORDER_PRODUCT_SELECTION_PROPOSAL,
            $contentInfo['id']
        );

        $productImgVideo = [];
        foreach ($resources as $resource) {
            if ($resource['extra']) {
                $productImgVideo[] = json_decode($resource['extra'], true);
            }
        }

        $arguments = array_merge($argument, ['productImgVideo' => $productImgVideo]);

        $form = self::getProductSelectionProposalForm(0, '', '', $arguments);

        $form['form'] = array_values($form['form']);


        if ($isWeb) {
            $shopInfos = (new RmsShopApi())->getShopByIds([$info->shopId], ['id', 'name', 'shopCode', 'addressPrefix'])['data']['shopList'] ?? [];
            $shopInfos = collect($shopInfos)->keyBy('id');

            $form['info']       = [
                'workOrderNo'    => $workOrderNo,
                'mobile'         => $argument['mobile'] ?? '',
                'name'           => $argument['name'] ?? '',
                'shopId'         => $info->shopId,
                'shopCode'       => $shopInfos[$info->shopId]['shopCode'] ?? '',
                'shopName'       => $shopInfos[$info->shopId]['name'] ?? '',
                'addressPrefix'  => $shopInfos[$info->shopId]['addressPrefix'] ?? '',
                'createdAt'      => date('Y-m-d H:i:s', $info->createdAt->timestamp),
                'type'           => $info->type,
                'typeText'       => WorkOrderProductSelectionProposalModel::TYPE_TEXT[$info->type] ?? '',
                'status'         => $info->status,
                'statusText'     => WorkOrderProductSelectionProposalModel::ADOPT_STATUS_TEXT[$info->status] ?? '',
                'dealStatus'     => $info->dealStatus,
                'dealStatusText' => WorkOrderProductSelectionProposalModel::DEAL_STATUS_TEXT[$info->dealStatus] ?? '',
            ];
            $form['statusText'] = enumToSelection(WorkOrderProductSelectionProposalModel::ADOPT_STATUS_TEXT);

            $form['operateHistory'] = WorkOrderOperateLogModel::query()
                ->where('workOrderNo', $workOrderNo)
                ->orderByDesc('id')->get()
                ->map(
                    function (
                        WorkOrderOperateLogModel $operateLogModel
                    ) {
                        $contentArr = json_decode($operateLogModel->content ?? '', true) ?? [];
                        if ($contentArr) {
                            $content = $contentArr['statusText'] ?? '';
                            if ($content) {
                                $content .= PHP_EOL;
                            }
                            $content .= '回复意见：' . ($contentArr['content'] ?? '');
                        } else {
                            $content = $operateLogModel->content ?? '';
                        }
                        return [
                            'content'         => $content,
                            'createdByUid'    => $operateLogModel->createdByUid,
                            'createdUsername' => $operateLogModel->createdUsername,
                            'createdAt'       => $operateLogModel->createdAt->format('Y-m-d H:i:s'),
                        ];
                    }
                )->toArray();
        } else {

            $status     = $info->status;
            $statusText = WorkOrderProductSelectionProposalModel::ADOPT_STATUS_TEXT[$info->status] ?? '';
            if (in_array($info->status, [WorkOrderProductSelectionProposalModel::ADOPT_STATUS_ONLINE, WorkOrderProductSelectionProposalModel::ADOPT_STATUS_HOT])) {
                $status = WorkOrderProductSelectionProposalModel::ADOPT_STATUS_ACCEPTED;// 已采纳
            }
            $completionTime = '';
            if ($info->status == WorkOrderProductSelectionProposalModel::ADOPT_STATUS_DEFAULT) {               // 评审中
                $month = date('m', strtotime('+1 month', $info->createdAt->timestamp));                        // 获取下个周期月份

                $feedback = "您的建议正在评审中,我们将在{$month}月15日前给您反馈";
            } else {

                // 后台记录最新的一次
                $lastInfo       = WorkOrderOperateLogModel::query()
                    ->where('workOrderNo', $workOrderNo)
                    ->where('type', WorkOrderOperateLogModel::TYPE_3)
                    ->orderByDesc('id')
                    ->first();
                $feedback       = json_decode($lastInfo->content ?? '', true)['content'] ?? '';
                $completionTime = $lastInfo ? $lastInfo->createdAt->format('Y-m-d H:i:s') : '';
            }

            $form['info'] = [
                'workOrderNo'    => $workOrderNo,
                'status'         => $status,
                'statusText'     => $statusText,
                'feedback'       => $feedback,       // 反馈详情
                'completionTime' => $completionTime, // 反馈详情时间
            ];
        }
        return $form;
    }

    /**
     * 数量自增
     * @param $identification
     * @return mixed
     */
    public static function autoincrementByRedis($identification)
    {
        $key = sprintf(self::AUTOINCREMENT_REDIS_KEY . '%s:%s', date('Ymd'), $identification);

        $res = Redis::incr($key, 1);
        if ($res == 1) {
            Redis::expireAt($key, strtotime(date('Y-m-d')) + 86401);
        }
        return $res;
    }

    /**
     * 选品建议表单
     */
    public static function getBaseForm()
    {
        AttributeWorkOrderSupport::getInstance('productTitle', AttributeWorkOrderSupport::INPUT_TYPE_TEXT, '产品名称')
            ->setValue('')
            ->setCustomAttribute(['placeholder', '请勿提报新鲜蔬菜类产品'])
            ->setValidateRules(ValidateSupport::getInstance(true)->setContentLength(1, 36));

        AttributeWorkOrderSupport::getInstance('productFlavor', AttributeWorkOrderSupport::INPUT_TYPE_TEXT, '产品口味')
            ->setValue('')
            ->setCustomAttribute(['placeholder', '如:麻辣/酸甜/五香/香辣/藤椒...'])
            ->setValidateRules(ValidateSupport::getInstance(true)->setContentLength(1, 255));

        AttributeWorkOrderSupport::getInstance('productBrand', AttributeWorkOrderSupport::INPUT_TYPE_TEXTAREA, '产品品牌或购买渠道')
            ->setValue('')
            ->setCustomAttribute(['placeholder', '如:正新鸡排'])
            ->setValidateRules(ValidateSupport::getInstance(true)->setContentLength(1, 1000));


        AttributeWorkOrderSupport::getInstance('productSellingPrice', AttributeWorkOrderSupport::INPUT_TYPE_TEXT, '产品售价')
            ->setValue('')
            ->setCustomAttribute(['placeholder', '如:5元/串、10元/份'])
            ->setValidateRules(ValidateSupport::getInstance(true)->setContentLength(1, 255));


        AttributeWorkOrderSupport::getInstance('desc', AttributeWorkOrderSupport::INPUT_TYPE_TEXTAREA, '推荐说明(不少于50字)')
            ->setValue('')
            ->setCustomAttribute(['placeholder', '请填写卖点、销量、适宜人群等'])
            ->setValidateRules(ValidateSupport::getInstance(true)->setContentLength(50, 1000));

        AttributeWorkOrderSupport::getInstance(
            'productImgVideo', AttributeWorkOrderSupport::INPUT_TYPE_IMG_VIDEO_CHECK_BOX,
            '产品图片/视频'
        )
            ->setCustomAttribute(['max', 20])
            ->setCustomAttribute(['videoCountLimit', 10])
            ->setCustomAttribute(['imgCountLimit', 10])
            ->setCustomAttribute(['download', true])
            ->setCustomAttribute(['check', true])
            ->setCustomAttribute(['desc', '可传多张图片/视频(包括生的、熟的图片)'])
            ->setCustomAttribute(['modeType', 'h5-generalization'])
            ->setValidateRules(ValidateSupport::getInstance(true)->setContentLength(1, 20));

        AttributeWorkOrderSupport::getInstance('mobile', AttributeWorkOrderSupport::INPUT_TYPE_MOBILE, '联系方式')
            ->setValue('')
            ->setCustomAttribute(['placeholder', '请填写联系方式'])
            ->setValidateRules(ValidateSupport::getInstance(true)->setContentLength(1, 36));


        AttributeWorkOrderSupport::getInstance('name', AttributeWorkOrderSupport::INPUT_TYPE_TEXT, '提报人')
            ->setValue('')
            ->setCustomAttribute(['placeholder', '请填写提报人'])
            ->setValidateRules(ValidateSupport::getInstance(true)->setContentLength(1, 36));

    }


    /**
     * 获取历史提交记录
     * @param array $data
     * @param int $pageNum
     * @param int $pageSize
     * @return array
     */
    public static function getLists(
        array $data,
        int $pageNum,
        int $pageSize
    ): array
    {
        $shopIds = $workOrderNos = [];
        if ($data['name']) {// 门店编号/门店名称/手机号/提报人
            $shopIds = ShopModel::query()
                ->where('name', 'like', "%{$data['name']}%")
                ->when(
                    is_numeric($data['name']), function ($query) use ($data) {
                    $query->orWhere('shopCode', 'like', "%{$data['name']}%");
                }
                )
                ->pluck('id')
                ->toArray();
            if (!$shopIds) {
                $shopIds = ['-1'];
            }

            $workOrderNos = WorkOrderProductSelectionProposalModel::query()
                ->join(
                    'work_order_apply_content', 'work_order_apply_content.workOrderNo',
                    'work_order_product_selection_proposal.workOrderNo'
                )
                ->whereRaw("JSON_EXTRACT(work_order_apply_content.content, '$**.name') LIKE '%{$data['name']}%'")
                ->when(
                    is_numeric($data['name']), function ($query) use ($data) {
                    $query->orWhereRaw("JSON_EXTRACT(work_order_apply_content.content, '$**.mobile') LIKE '%{$data['name']}%'");
                }
                )
                ->select(['work_order_product_selection_proposal.workOrderNo'])
                ->pluck('workOrderNo')
                ->toArray();
            if (!$workOrderNos) {
                $workOrderNos = ['-1'];
            }
        }
        if ($data['productName']) {// 产品名称/品牌
            $workOrderNosByProductName = WorkOrderProductSelectionProposalModel::query()
                ->join(
                    'work_order_apply_content', 'work_order_apply_content.workOrderNo',
                    'work_order_product_selection_proposal.workOrderNo'
                )
                ->whereRaw("JSON_EXTRACT(work_order_apply_content.content, '$**.productTitle') LIKE '%{$data['productName']}%'")
                ->orWhereRaw("JSON_EXTRACT(work_order_apply_content.content, '$**.productBrand') LIKE '%{$data['productName']}%'")
                ->select(['work_order_product_selection_proposal.workOrderNo'])
                ->pluck('workOrderNo')
                ->toArray();
            if (!$workOrderNosByProductName) {
                $workOrderNosByProductName = ['-1'];
            }
            $workOrderNos = array_unique(array_merge($workOrderNos, $workOrderNosByProductName));
        }

        $paginates = WorkOrderProductSelectionProposalModel::query()
            ->with(['contentRel'])
            ->when(
                $shopIds || $workOrderNos, function ($query) use ($shopIds, $workOrderNos) {
                $query->where(
                    function ($query) use ($shopIds, $workOrderNos) {
                        if ($shopIds) {
                            $query->whereIn('shopId', $shopIds);
                        }
                        if ($workOrderNos) {
                            $query->orWhereIn('workOrderNo', $workOrderNos);
                        }
                    }
                );
            }
            )
            ->when(
                $data['startTime'] && $data['endTime'], function ($query) use ($data) {
                $query->whereBetween('createdAt', [$data['startTime'], $data['endTime']]);// 创建时间
            }
            )
            ->when(
                $data['status'], function ($query) use ($data) {
                $query->whereIn('status', $data['status']);
            }
            )
            ->when(
                $data['dealStatus'], function ($query) use ($data) {
                $query->whereIn('dealStatus', $data['dealStatus']);
            }
            )
            ->orderByDesc('createdAt')
            ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        $shopIds   = $paginates->pluck('shopId')->unique()->toArray();
        $shopInfos = (new RmsShopApi())->getShopByIds($shopIds, ['id', 'name', 'shopCode'])['data']['shopList'] ?? [];
        $shopInfos = collect($shopInfos)->keyBy('id');

        return [
            'lists'          => $paginates->map(
                function ($item) use ($shopInfos) {
                    $content = json_decode($item->contentRel->content ?? '', true) ?? [];
                    return [
                        'workOrderNo'    => $item->workOrderNo,
                        'productTitle'   => $content['productTitle'] ?? '',
                        'productBrand'   => $content['productBrand'] ?? '',
                        'name'           => $content['name'] ?? '',
                        'shopCode'       => $shopInfos[$item->shopId]['shopCode'] ?? '',
                        'shopName'       => $shopInfos[$item->shopId]['name'] ?? '',
                        'createdAt'      => date('Y-m-d H:i:s', $item->createdAt->timestamp),
                        'type'           => $item->type,
                        'typeText'       => WorkOrderProductSelectionProposalModel::TYPE_TEXT[$item->type] ?? '',
                        'status'         => $item->status,
                        'statusText'     => WorkOrderProductSelectionProposalModel::ADOPT_STATUS_TEXT[$item->status] ?? '',
                        'dealStatus'     => $item->dealStatus,
                        'dealStatusText' => WorkOrderProductSelectionProposalModel::DEAL_STATUS_TEXT[$item->dealStatus] ?? '',
                    ];
                }
            ),
            'pageNum'        => $pageNum,
            'pageSize'       => $pageSize,
            'count'          => $paginates->total(),
            'statusText'     => enumToSelection(WorkOrderProductSelectionProposalModel::ADOPT_STATUS_TEXT),
            'dealStatusText' => enumToSelection(WorkOrderProductSelectionProposalModel::DEAL_STATUS_TEXT),
        ];
    }

    /**
     * 通过工单号修改状态
     * @param string $workOrderNo
     * @param int $userId
     * @param string $userName
     * @param int $status
     * @param string $content
     * @return array
     */
    public static function updateStatus(string $workOrderNo, int $userId, string $userName, int $status, string $content): array
    {
        $contentArr = [];
        if ($status) {
            WorkOrderProductSelectionProposalModel::query()
                ->where('workOrderNo', $workOrderNo)
                ->update(['status' => $status, 'dealStatus' => WorkOrderProductSelectionProposalModel::DEAL_STATUS_REPLIED]);

            $statusText               = '采纳状态：' . WorkOrderProductSelectionProposalModel::ADOPT_STATUS_TEXT[$status] ?? '';
            $contentArr['statusText'] = $statusText;
        }
        if ($content) {
            $contentArr['content'] = $content;
        }

        //日志
        WorkOrderOperateLogModel::generateOperateLog(
            $workOrderNo,
            MissionEnum::STEP_4,
            WorkOrderOperateLogModel::TYPE_3,
            $userName,
            $userId,
            json_encode($contentArr, JSON_UNESCAPED_UNICODE)
        );
        return [];
    }
}
